﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; 
using System.Net;
using System.Net.Sockets;
namespace MyUtils
{
     public class NtpClient
    {
        /// <summary>
        /// Gets the current DateTime from time-a.nist.gov.
        /// </summary>
        /// <returns>A DateTime containing the current time.</returns>
        public static DateTime GetNetworkTime()
        {
            //if get current time in a npt server fail, so get next npt server in NTP server list
            DateTime dt=new DateTime();
            for (int i = 0;i< (int)ConstString.ARR_STR_NTP.Length; i++)
            {
                DateTime dtget=GetNetworkTime(ConstString.ARR_STR_NTP[i]);
                if(!dt.Equals(dtget))
                {
                    return dtget;
                }
            }
            return dt;
        }

        /// <summary>
        /// Gets the current DateTime from <paramref name="ntpServer"/>.
        /// </summary>
        /// <param name="ntpServer">The hostname of the NTP server.</param>
        /// <returns>A DateTime containing the current time.</returns>
        public static DateTime GetNetworkTime(string ntpServer)
        {
            try
            {
                IPAddress[] address = Dns.GetHostEntry(ntpServer).AddressList;

                if (address == null || address.Length == 0)
                    throw new ArgumentException("Could not resolve ip address from '" + ntpServer + "'.", "ntpServer");

                IPEndPoint ep = new IPEndPoint(address[0], 123);

                return GetNetworkTime(ep);
            }
            catch
            {
                return new DateTime();
            }
        }

        /// <summary>
        /// Gets the current DateTime form <paramref name="ep"/> IPEndPoint.
        /// </summary>
        /// <param name="ep">The IPEndPoint to connect to.</param>
        /// <returns>A DateTime containing the current time.</returns>
        public static DateTime GetNetworkTime(IPEndPoint ep)
        {
            try
            {
                Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                s.ReceiveTimeout = 2000;
                s.Connect(ep);

                byte[] ntpData = new byte[48]; // RFC 2030
                ntpData[0] = 0x1B;
                for (int i = 1; i < 48; i++)
                    ntpData[i] = 0;

                s.Send(ntpData);
                s.Receive(ntpData);

                byte offsetTransmitTime = 40;
                ulong intpart = 0;
                ulong fractpart = 0;

                for (int i = 0; i <= 3; i++)
                    intpart = 256 * intpart + ntpData[offsetTransmitTime + i];

                for (int i = 4; i <= 7; i++)
                    fractpart = 256 * fractpart + ntpData[offsetTransmitTime + i];

                ulong milliseconds = (intpart * 1000 + (fractpart * 1000) / 0x100000000L);
                s.Close();

                TimeSpan timeSpan = TimeSpan.FromTicks((long)milliseconds * TimeSpan.TicksPerMillisecond);

                DateTime dateTime = new DateTime(1900, 1, 1);
                dateTime += timeSpan;

               TimeSpan offsetAmount = TimeZone.CurrentTimeZone.GetUtcOffset(dateTime);
                DateTime networkDateTime = (dateTime /*+ offsetAmount)*/);

                return networkDateTime;
            }
            catch
            {
                return new DateTime();
            }
        }
    }
}
 